#!/usr/bin/env python

import pygame
from numpy import *
import pygame.draw
import pygame.key
import math
import os
import struct, socket, SocketServer, threading, sys
import transform

clients = []
PLAYERS_NUM = 3
running = None
pground = None
gameBorders = None
gameSize = None
gameLeft = None
gameTop = None
lock = None
clientsLock = None
screen = None
WHITE = 255, 255, 255
GREEN = 0, 255, 0
BLACK = 0, 0, 0
BLUE = 0, 0, 255
RED = 255, 0, 0
#CUBE = 10
#SCREEN_SIZE = (320, 480)
#PLAYER_SIZE = (CUBE, CUBE)
#ARRAY_SIZE = (SCREEN_SIZE[1] / PLAYER_SIZE[1], SCREEN_SIZE[0] / PLAYER_SIZE[0])
#MOVE = CUBE
def sendToAll(data):
   global clients
   clientsLock.acquire()
   for c in clients:
      c[1].sendall(data)
   clientsLock.release()
def onFrame(i, j):
	if i not in (0, ARRAY_SIZE[0] - 1) and j not in (0, ARRAY_SIZE[1] - 1) :
		return False
	return True
class Player:
    def __init__(self, pid, x=0, y=0, color=(0, 0, 0)):
        self.x = x
        self.color = color
        self.y = y
        self.id = pid
        self.trail = []
        self.loops = 0
        self.leaveTrail = False

    def getPos(self):
        return (self.x, self.y)
    def canMove(self, loc, size):
        x, y = loc
        if x >= size[0] or y >= size[1] or x < 0 or y < 0:
            return False
        return True
    def move(self, loc, size):
        movement = self.canMove(loc, size)
        if movement:
            self.x, self.y = loc
            msg = struct.pack('!biii', 0x4,self.id,self.x,self.y)
            sendToAll(msg)
            #plground.field[self.getFieldLoc()[0]][self.getFieldLoc()[1]] = (self.id,0)

    def getFieldY(self):
        return int(math.floor(self.y))
    def getFieldX(self):
        return int(math.floor(self.x))
class Cell:
    def __init__(self, isBorder=False):
        self.isBorder = isBorder;
        self.players = []
        self.ownedBy = 0
        self.isCalc = 0
    def __str__(self):
        #return "hi"
        return str(self.players) #+str(self.isBorder) + + self(self.ownedBy)
    #def __call__(self,arguments):
    #    return self
    def addPlayer(self, player):
        if self.players.count(player) == 0:
            self.players.append(player)
    def removePlayer(self, player):
        if self.players.count(player) == 1:
            self.players.remove(player)
class PlayGround:
    def __getAreaSize(self, x, y, p, flag):
        field = self.field
        for (s,t) in self.players[p].trail:
        	field[s][t].isCalc = 2
        "using flood file determine the area size"
        edge = None
        count = 1
        isEnemyContained = False
        if self.isWithinField(y, x) and field[y][x].ownedBy not in (0, p):
        		isEnemyContained = True
        elif self.isWithinField(y, x) and field[y][x].isCalc == 0 and field[y][x].ownedBy == 0:
        		field[y][x].isCalc = flag
        		if field[y][x].ownedBy != p:
        			count = count + 1
        			edge = [(y, x)]
        while edge:
            newedge = []
            for (y, x) in edge:
                for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1)):
                    if self.isWithinField(s, t) and field[s][t].ownedBy not in (0, p):
                        isEnemyContained = True
                    elif self.isWithinField(s, t) and field[s][t].isCalc == 0 and field[s][t].ownedBy == 0:
                        field[s][t].isCalc = flag
                        if field[s][t].ownedBy != p:
                            count = count + 1
                        newedge.append((s, t))
            edge = newedge
        return (count, isEnemyContained)
        
    def __isAreaBlocked(self, area, p):
        field = self.field
        x,y = area[3]
        print "x="+str(x)+"\ny="+str(y)
        flag = field[y][x].isCalc
        count = 1
        edge = [(y, x)]
        tmpB = []
        for i in range(0, self.m):
            tmpB.append([])
            for j in range(0, self.n):
                tmpB[i].append(0);
        tmpB[y][x]=1
        while edge:
            newedge = []
            for (y, x) in edge:
                for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1)):
                	if self.isWithinField(s, t) and tmpB[s][t]!=1 and ((field[s][t].isCalc != 2) or (field[s][t].isCalc == 2 and field[s][t].ownedBy not in (0,p))):
                		tmpB[s][t]=1
                		if field[s][t].isCalc == 0:
                			count = count + 1
                		newedge.append((s, t))
                	if count>area[0]:
                		return False
            edge = newedge
        return True
        
    def __getRouteToEdge(self, player, x, y, start):
    	if self.__isInside((y, x)):
    		curP = self.players[player]
    		foundRoute = False
    		for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1)):
		        if self.isWithinField(s, t) and self.field[s][t].isBorder and self.field[s][t].ownedBy == player and (s, t) not in curP.trail:
		            if start:
		           	curP.trail.insert(0, (s, t))
		            else:
		            	curP.trail.append((s, t))
		            y, x = s, t
		            print curP.trail
		            if self.__getRouteToEdge(player, t, s, start):
		            	return True
                    	    else:
                    	    	curP.trail.remove((s, t))
                return False    	    	
        else:
        	return True
    
    def __completeTrail(self, player):
        '''curP=self.players[player]
        y,x = curP.trail[0]
        prevs = [curP.trail[0]]
        while self.__isInside((y,x)):
            print "sad"
            for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1)):
                if self.isWithinField(s, t) and self.field[s][t].isBorder and self.field[s][t].ownedBy==player and (s,t) not in prevs:
                    curP.trail.insert(0, (s,t))
                    y,x = s,t
                    prevs.append((s,t))
                    print curP.trail
                    break
        y,x = curP.trail[-1]
        prevs = [curP.trail[-1]]
        while self.__isInside((y,x)):
            print "sad2"
            for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1)):
                if self.isWithinField(s, t) and self.field[s][t].isBorder and self.field[s][t].ownedBy==player and (s,t) not in prevs:
                    curP.trail.append((s,t))
                    prevs.append((s,t))
                    y,x = (s,t)
                    print curP.trail
                    break'''
        curP = self.players[player]
        y, x = curP.trail[0]
        self.__getRouteToEdge(player, x, y, True)
        y, x = curP.trail[-1]
        self.__getRouteToEdge(player, x, y, False)


    def __EraseClac(self, player):
        for i in xrange(self.m):
            for j in xrange(self.n):
                if self.field[i][j].isCalc > 2:
                    self.field[i][j].isCalc = 0

    def __fillArea(self, flag, player):
        
        for i in xrange(self.m):
            for j in xrange(self.n):
                if self.field[i][j].isCalc == flag and self.field[i][j].ownedBy == 0:
                    self.field[i][j].isCalc = 2
                    self.field[i][j].ownedBy = player
                    msg = struct.pack('!biii', 0x3,player,j,i)
                    sendToAll(msg)
                    self.freeCells = self.freeCells - 1
                    self.players[player].loops = 0


    def getCell(self, player):
        #print "Field Len: " + str(len(self.field))
        #print "Players Arr Len: " + str(len(self.players))
        #print "Player Num: " + str(player)
        #print "Player Loc: " + str((self.players[player].getFieldX(), self.players[player].getFieldY()))
        return self.field[self.players[player].getFieldY()][self.players[player].getFieldX()]
    
    def __isInside(self, (x, y)):
        # TODO: check that n and m is matching to x and y
        if x > 0 and x < self.n - 1 and y > 0 and y < self.m - 1:
            return True
        return False
    
    def __repairBorders(self, player):
        for i in xrange(self.m):
            for j in xrange(self.n):
                if self.field[i][j].isBorder:
                    countNear = 8
                    if self.isWithinField(i - 1, j) and self.field[i - 1][j].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i + 1, j) and self.field[i + 1][j].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i, j - 1) and self.field[i][j - 1].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i, j + 1) and self.field[i][j + 1].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i - 1, j - 1) and self.field[i - 1][j - 1].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i + 1, j + 1) and self.field[i + 1][j + 1].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i + 1, j - 1) and self.field[i + 1][j - 1].ownedBy == player:
                        countNear = countNear - 1
                    if self.isWithinField(i - 1, j + 1) and self.field[i - 1][j + 1].ownedBy == player:
                        countNear = countNear - 1
                    if countNear == 0:
                        self.field[i][j].isBorder = False

    def __init__(self, size, playerSize=1):
        self.n = size[0];
        self.m = size[1];
        #print "Size Is: "+str(size)
        self.field = []
        self.freeCells = self.m * self.n
        for i in range(0, self.m):
            self.field.append([])
            for j in range(0, self.n):
                self.field[i].append(Cell());
        for i in range(0, self.n):
            self.field[0][i].isBorder = True
            self.field[self.m - 1][i].isBorder = True
        for i in range(0, self.m):
            self.field[i][0].isBorder = True
            self.field[i][self.n - 1].isBorder = True
        self.players = [0, Player(1, 0, 0, GREEN), Player(2, 0, 0, RED), Player(3, 0, 0, BLUE)]
        #print str((self.players[1].x,self.players[1].y))
        #print str((self.players[2].x,self.players[2].y))
        #self.players[1] = Player(1,SCREEN_SIZE[0]/2,0,BLUE)
        #self.players[2] = Player(2,SCREEN_SIZE[0]/2,SCREEN_SIZE[1]-MOVE,RED)
        #self.getCell(1).addPlayer(self.players[1].id)
        #self.getCell(2).addPlayer(self.players[2].id)
    def isWithinField(self, y, x):
        return y >= 0 and y < self.m and x >= 0 and x < self.n
    def deleteTrail(self, player):
        msg = struct.pack('!bi', 0x2,player)
        sendToAll(msg)
        self.players[player].loops = 0
        for i in self.players[player].trail:
            self.field[i[0]][i[1]].removePlayer(player)
        self.players[player].trail = []
    def resetTrail(self, player):
        msg = struct.pack('!bi', 0x2,player)
        sendToAll(msg)
        self.players[player].trail = []
    def fillTrail(self, player):
        for(i, j) in self.players[player].trail:
            self.field[i][j].ownedBy = player
            self.field[i][j].isBorder = True
            self.freeCells = self.freeCells - 1
            msg = struct.pack('!biii', 0x3,player,j,i)
            sendToAll(msg)
    def movePlayer(self, player, loc):
        print "called with: "+str(loc)
        print "for player: "+str(player)
        curP = self.players[player]
        if self.players[player].canMove(loc,(self.n,self.m)):
            prevCell = self.getCell(player)
            (tY, tX) = (curP.getFieldY(), curP.getFieldX())
            self.players[player].move(loc, (self.n,self.m))
            currCell = self.getCell(player)
            if prevCell.ownedBy != 0 and currCell.ownedBy != 0 and currCell.ownedBy == prevCell.ownedBy:
                curP.leaveTrail = False
            # if on enemy trail delete enemy trail
            for p in currCell.players:
                if p != player and currCell.ownedBy == 0:
                    self.deleteTrail(p)
                    self.players[p].leaveTrail = False
            #if currCell.ownedBy not in (0,player):
            #    self.deleteTrail(player)
            #append a trail only if left the border and have trail
            if (not prevCell.isBorder or not currCell.isBorder) and curP.leaveTrail:
                curP.trail.append((tY, tX))
                msg = struct.pack('!biii', 0x1,player,tX,tY)
                sendToAll(msg)
                prevCell.addPlayer(player)
                #if closing trail
            elif prevCell.isBorder and currCell.isBorder:
                curP.leaveTrail = False
      	   #checking for loops in trail
            if (curP.getFieldY(), curP.getFieldX()) in curP.trail:
                curP.loops = curP.loops + 1
        #        lst = []
        #        afterLoop = False
        #        for x in curP.trail:
        #            if afterLoop:
        #                lst.append(x)
        #            elif x == (curP.getFieldY(), curP.getFieldX()):
        #                afterLoop = True
        #        for x in lst:
        #            curP.trail.remove(x)
        #        curP.loops.append(lst)
            #in case of meeting a border
            if currCell.isBorder and (currCell.ownedBy == 0 or currCell.ownedBy == player):
                #print "MEETING BORDER"
                if curP.leaveTrail == True or (not self.__isInside((curP.getFieldX(),curP.getFieldY())) and self.__isInside((tX,tY)) and prevCell.ownedBy==player):
            #add last point to the trail
                    curP.trail.append((curP.getFieldY(), curP.getFieldX()))
                    currCell.addPlayer(player)
                    prevTrail = curP.trail
                    #self.__completeTrail(player)
                    print 'finding a cell to start calculating closing area'
                    size = None
                    floadArr = []
                    count = 3
                    falseAreas = [0,0,0,0,  0,0,0,0] # UP, DOWN, RIGHT, LEFT, Diagonal...
                    firstCellIsNearEnemy = []
                    lastCellIsNearEnemy = []
                    if self.isWithinField(curP.trail[0][1] + 1, curP.trail[0][0]) and self.field[curP.trail[0][1] + 1][curP.trail[0][0]].ownedBy not in (0,player):
                    	firstCellIsNearEnemy.append(1)
                    if self.isWithinField(curP.trail[0][1] - 1, curP.trail[0][0]) and self.field[curP.trail[0][1] - 1][curP.trail[0][0]].ownedBy not in (0,player):
                    	firstCellIsNearEnemy.append(0)
                    if self.isWithinField(curP.trail[0][1], curP.trail[0][0] + 1) and self.field[curP.trail[0][1]][curP.trail[0][0] + 1].ownedBy not in (0,player):
                    	firstCellIsNearEnemy.append(3)
                    if self.isWithinField(curP.trail[0][1], curP.trail[0][0] - 1) and self.field[curP.trail[0][1]][curP.trail[0][0] - 1].ownedBy not in (0,player):
                    	firstCellIsNearEnemy.append(2)
                    if self.isWithinField(curP.trail[-1][1] + 1, curP.trail[-1][0]) and self.field[curP.trail[-1][1] + 1][curP.trail[-1][0]].ownedBy not in (0,player):
                    	lastCellIsNearEnemy.append(1)
                    if self.isWithinField(curP.trail[-1][1] - 1, curP.trail[-1][0]) and self.field[curP.trail[-1][1] - 1][curP.trail[-1][0]].ownedBy not in (0,player):
                    	lastCellIsNearEnemy.append(0)
                    if self.isWithinField(curP.trail[-1][1], curP.trail[-1][0] + 1) and self.field[curP.trail[-1][1]][curP.trail[-1][0] + 1].ownedBy not in (0,player):
                    	lastCellIsNearEnemy.append(3)
                    if self.isWithinField(curP.trail[-1][1], curP.trail[-1][0] - 1) and self.field[curP.trail[-1][1]][curP.trail[-1][0] - 1].ownedBy not in (0,player):
                    	lastCellIsNearEnemy.append(2)
                    sumSizes = 0
                    for k in curP.trail:
                        if k not in (curP.trail[0],curP.trail[-1]):
	                        for (s, t) in ((k[0] - 1, k[1]), (k[0] + 1, k[1]), (k[0], k[1] + 1), (k[0], k[1] - 1)):
        	                    if self.isWithinField(s, t) and self.field[s][t].isCalc == 0 and self.field[s][t].ownedBy == 0 and (s, t) not in curP.trail:
        	                    	size, isEnemyContained = self.__getAreaSize(t, s, player, count)
        	                    	sumSizes = sumSizes+size
        	                    	print size
        	                    	print isEnemyContained
        	                    	print count
        	                    	print '-------------'
        	                    	'''if size!=None and (not minSizeArr.empty() or size<minSizeArr[0][0]):
        	                    	    minSize = size
        	                         minFlag = count
        	                         minEnemyContained = isEnemyContained'''
        	                    	floadArr.append((size, count, isEnemyContained, (t,s), True))
        	                    	count = count + 1
        	                    elif self.isWithinField(s, t) and self.field[s][t].ownedBy not in (0,player):
        	                    	size, isEnemyContained = self.__getAreaSize(t, s, player, count)
        	                    	floadArr.append((size, count, isEnemyContained, (t,s), False))
        	                    	count = count + 1
        	                    	if k[0]-s == 1:
        	                    		falseAreas[0] = falseAreas[0]+1
        	                    	elif k[0]-s == -1:
        	                    		falseAreas[1] = falseAreas[1]+1
        	                    	elif k[1]-t == 1:
        	                    		falseAreas[2] = falseAreas[2]+1
        	                    	elif k[1]-t == -1:
        	                    		falseAreas[3] = falseAreas[3]+1
	                        if self.isWithinField(k[0]+1, k[1]+1) and self.field[k[0]+1][k[1]+1].ownedBy not in (0,player):
	                        	falseAreas[4] = falseAreas[4]+1
	                        if self.isWithinField(k[0]-1, k[1]+1) and self.field[k[0]-1][k[1]+1].ownedBy not in (0,player):
	                        	falseAreas[5] = falseAreas[5]+1
	                        if self.isWithinField(k[0]+1, k[1]-1) and self.field[k[0]+1][k[1]-1].ownedBy not in (0,player):
	                        	falseAreas[6] = falseAreas[6]+1
	                        if self.isWithinField(k[0]-1, k[1]-1) and self.field[k[0]-1][k[1]-1].ownedBy not in (0,player):
	                        	falseAreas[7] = falseAreas[7]+1
                    floadArr = sorted(floadArr, key=lambda fload: fload[0], reverse=True)
                    self.printField()
                    '''reachBorder = False
                    for k in curP.trail:
                        count = 0
                        for (s, t) in ((k[0] + 1, k[1]), (k[0] - 1, k[1]), (k[0], k[1] + 1), (k[0], k[1] - 1)):
	                        if reachBorder and self.isWithinField(s, t) and self.field[s][t].ownedBy == 0:
	                        	count = count + 1
	                        elif self.isWithinField(s, t) and self.field[s][t].ownedBy == player and self.field[s][t].isBorder:
	                        	reachBorder = True
	                        	break
                        if count == 4:
	                        curP.loops = curP.loops + 1
	                        reachBorder = False
                    print str(curP.loops)'''
                    '''for loop in xrange(curP.loops + 1):
                    # The first statement is only an optimization.
		                 if count > 4 and floadArr[loop][1] != None:
		                     print "a"
		                     if not floadArr[loop][2]:
		                         self.__fillArea(floadArr[loop][1], player)
		                 elif floadArr[loop][1] != None:
		                     neighbors = set()
		                     for y, x in curP.trail:
		                     	for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1)):
		                     		if self.isWithinField(s, t):
		                     			neighbors.add(self.field[s][t].isCalc)
		                     # 2 is for occupaid territory
		                     print str(neighbors)
		                     if 2 in neighbors:
		                     	neighbors.remove(2)
		                     if neighbors.__len__() > 1 and not floadArr[loop][2]:
		                         print "b"
		                         self.__fillArea(floadArr[loop][1], player)'''
                    '''else:
                        fill = True
                        for i in range(0, self.n):
                            for j in range(0, self.m):
                                if self.field[i][j].isCalc == False and self.field[i][j].ownedBy not in (player,0):
                                    fill = False
                        if fill:
                            self.__fillArea(False, player)'''
                    hallowAreaProtection = False
                    if len(floadArr)<=1:
                    	hallowAreaProtection = True
                    print str(floadArr)
                    print "****\t\t" + str(falseAreas)+"\t\t******"
                    print "****\t\t" + str(len(curP.trail))+"\t\t******"
                    print "****\t\t" + str(lastCellIsNearEnemy)+"\t\t******"
                    print "****\t\t" + str(firstCellIsNearEnemy)+"\t\t******"
                    floadArr = sorted(floadArr, key=lambda fload: fload[4])
                    while len(floadArr)>0 and not floadArr[0][4]:
		              	floadArr.pop(0)
                    floadArr = sorted(floadArr, key=lambda fload: fload[0], reverse=True)
                    print str(floadArr)
                    tooCloseToEnemy = False
                    for i in range(0,4):
                    	print str(sum(falseAreas))+">="+str((len(curP.trail)-2))
                    	if sum(falseAreas)>=(len(curP.trail)-2) and (i in firstCellIsNearEnemy and i in lastCellIsNearEnemy):
                    		tooCloseToEnemy=True
                    if len(floadArr)>1:
                    	poped = False
                    	for area in floadArr:
                    		if not self.__isAreaBlocked(area,player):
                    			print "Removed: "+ str(floadArr.remove(area))
                    			poped = True
                    			print str(floadArr)
                    	if not poped:
                    		print "Removed: "+str(floadArr.pop(0))
                    floadArr.reverse()
                    while len(floadArr)>0 and floadArr[0][0]>sumSizes/2:
		              	floadArr.pop(0)
                    for tmpo in floadArr:
                    # The first statement is only an optimization.
		                 print "**********************************\n"+str(tmpo)+"\n**********************************"
		                 if tmpo[1] != None:
		                     if not tmpo[2] and not hallowAreaProtection and not tooCloseToEnemy:
		                         self.__fillArea(tmpo[1], player)
		                     '''neighbors = set()
		                     nearEnemy = True
		                     for y, x in curP.trail:
		                     	sidesNearEnemy = 0
		                     	for (s, t) in ((y + 1, x), (y - 1, x), (y, x + 1), (y, x - 1), (y + 1, x - 1), (y - 1, x + 1), (y + 1, x + 1), (y - 1, x - 1)):
		                     		if self.isWithinField(s, t):
		                     			neighbors.add(self.field[s][t].isCalc)
		                     			if self.field[s][t].ownedBy not in (0,player):
		                     				sidesNearEnemy = sidesNearEnemy+1
		                     	# first condition is for the first cell in the trail
		                     	if self.field[y][x].ownedBy==0 and sidesNearEnemy<1:
		                     		print "Not near enemy: ("+str(x)+","+str(y)+")"
		                     		nearEnemy=False
		                     # 2 is for occupaid territory
		                     print str(neighbors)
		                     if 2 in neighbors:
		                     	neighbors.remove(2)
		                     if (neighbors.__len__() > 1 or nearEnemy) and not tmpo[2]:
		                         print "b"
		                         self.__fillArea(tmpo[1], player)'''
                    self.fillTrail(player)
                    self.__repairBorders(player)
                    self.resetTrail(player)
                    self.__EraseClac(player)
                else:
                    curP.leaveTrail = True
                    #print "leaveTrail"
        		#got to enamy territory
            elif currCell.isBorder and currCell.ownedBy not in (0, player):
                self.deleteTrail(player)
                curP.leaveTrail = False
            #if currCell.ownedBy != 0 and currCell.ownedBy != player:
                #delete trail
            #if other players left trail on this cell and currCell.ownedBy == 0
                #delete other players trails
    def printField(self):
        print "\n\n"
        a = arange(self.m * self.n).reshape(self.m, self.n)
        for i in range(0, len(self.field)):
            for j in range(0, len(self.field[i])):
                a[i][j] = self.field[i][j].isCalc
        print a
    def printField2(self):
        print "\n\n"
        a = arange(self.m * self.n).reshape(self.n, self.m)
        for i in range(0, len(self.field)):
            for j in range(0, len(self.field[i])):
                a[i][j] = self.field[i][j].ownedBy
        print a

def restart():
    #screen.fill((255, 255, 255))
    pground.__init__()
    
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
	pass

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
    	"""
    	The RequestHandler class for our server.

    	It is instantiated once per connection to the server, and must
    	override the handle() method to implement communication to the
    	client.
    	"""
    	
    	def handle(self):
    	    	global clients
    	    	global pground
    	    	global gameBorders
    	    	global gameSize
    	    	global gameLeft, gameTop
    	    	cur_thread = threading.currentThread()
    	    	data = self.request.recv(1)
    	    	char, = struct.unpack("!c",data)
    	    	print str(char)
    	    	print "%s Connected!" % self.client_address[0]
    	    	clientsLock.acquire()
    	    	clientId = len(clients)+1
    	    	if clientId==1:
    	    		data = self.request.recv(32)
    	    		while len(data)<32:
    	    			data += self.request.recv(32-len(data))
    	    		a1,a2,b1,b2,c1,c2,d1,d2  = struct.unpack("!iiiiiiii",data)
    	    		print str((a1,a2))
    	    		print str((b1,b2))
    	    		print str((c1,c2))
    	    		print str((d1,d2))
    	    		gameSize ,geoPoints = transform.defineMatrix((a1,a2),(b1,b2),(c1,c2),(d1,d2))
    	    		print "Game Size is: "+str(gameSize)
    	    		gameLeft, gameTop, gameBorders = transform.toGameMatrix(geoPoints)
    	    		pground = PlayGround(gameSize)
    	    	clients.append((clientId,self.request, 0))
    	    	clientsLock.release()
    	    	if clientId == PLAYERS_NUM:
    	    		msg = struct.pack('!bii', 0x5, gameSize[0],gameSize[1])
    	    		sendToAll(msg)
    	    	prevLoc = None
    	    	while running:
    	    		# self.request is the TCP socket connected to the client
    	    		data = self.request.recv(4)
    	    		while len(data)<4:
    	    			data += self.request.recv(4-len(data))
    	    		#print "dataX: "+str(data)
    	    		x, = struct.unpack("!i",data)
    	    		data = self.request.recv(4)
    	    		while len(data)<4:
    	    			data += self.request.recv(4-len(data))
    	    		#print "dataY: "+str(data)
    	    		y, = struct.unpack("!i",data)
    	    		#print "points-Before: "+str((x,y))
    	    		x, y = transform.getMatrixPos((transform.getUTM((x,y))),(gameLeft,gameTop))
    	    		if prevLoc != None:
    	    			dirX = x - prevLoc[0]
    	    			dirY = y - prevLoc[1]
    	    			if dirX!=0:
    	    				dirX = dirX/abs(dirX)
    	    			if dirY!=0:
    	    				dirY = dirY/abs(dirY)
    	    			vec = [dirX, dirY]
    	    			while prevLoc[0]!=x:
    	    				prevLoc[0] += vec[0]
    	    				if pground.isWithinField(y,x):
    	    					lock.acquire()
    	    					pground.movePlayer(clientId, (prevLoc[0],prevLoc[1]))
    	    					lock.release()
    	    				else:
    	    					break
    	    			while prevLoc[1]!=y:
    	    				prevLoc[1] += vec[1]
    	    				if pground.isWithinField(y,x):
    	    					lock.acquire()
    	    					pground.movePlayer(clientId, (prevLoc[0],prevLoc[1]))
    	    					lock.release()
    	    				else:
    	    					break
    	    		#print "points-After: "+str((x,y))
    	    		else:
	    	    		if pground.isWithinField(y,x):
	    	    			#print "In field!"
	    	    			lock.acquire()
	    	    			pground.movePlayer(clientId, (x,y))
	    	    			lock.release()
	    	    			prevLoc = [x,y]
def main():
    global running
    global lock
    global screen
    global clientsLock
    lock = threading.Semaphore()
    clientsLock = threading.Semaphore()
    running = True
#    if "-p" in sys.argv:
#    	PORT
    HOST, PORT = sys.argv[1], int(sys.argv[2])
    #pygame.init()
    #pygame.key.set_repeat(30, 30)
    #screen = pygame.display.set_mode(SCREEN_SIZE)
    #os.environ['SDL_VIDEO_WINDOW_POS'] = '150,150'
    #draw(screen)
    #pygame.display.flip()
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    server.serve_forever()
    #screen.fill((255, 255, 255))
    #screen.blit(s, (0, 0))
    #pygame.display.flip()
    #pygame.quit()
    
if __name__ == '__main__':
    main()

